package com.ticket.system.service.impl;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.ticket.common.constant.PerformConstants;
import com.ticket.common.core.domain.model.LoginUser;
import com.ticket.common.exception.ServiceException;
import com.ticket.common.utils.DateUtils;
import com.ticket.common.utils.SecurityUtils;
import com.ticket.system.domain.*;
import com.ticket.system.domain.vo.OrderDetailVo;
import com.ticket.system.domain.vo.OrderVo;
import com.ticket.system.mapper.*;
import com.ticket.system.service.IYanchuRefundBackendOrderService;
import com.ticket.system.service.IYanchuScoreService;
import com.ticket.system.service.IYanchuSeatService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import static java.util.stream.Collectors.toList;

/**
 * 出票退款单Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-02-19
 */
@Service
public class YanchuRefundBackendOrderServiceImpl implements IYanchuRefundBackendOrderService 
{
    private static final Logger logger = LoggerFactory.getLogger(YanchuRefundBackendOrderServiceImpl.class);
    @Autowired
    private YanchuRefundBackendOrderMapper yanchuRefundBackendOrderMapper;
    @Autowired
    private YuanchuRefundBackendOrderDetailMapper yuanchuRefundBackendOrderDetailMapper;
    @Autowired
    private YanchuOrderMapper yanchuOrderMapper;

    @Autowired
    private YanchuOrderDetailMapper yanchuOrderDetailMapper;

    @Autowired
    private YanchuSeatMapper yanchuSeatMapper;

    @Autowired
    private IYanchuSeatService iYanchuSeatService;
    @Autowired
    private IYanchuScoreService iYanchuScoreService;

    /**
     * 查询出票退款单
     * 
     * @param id 出票退款单主键
     * @return 出票退款单
     */
    @Override
    public YanchuRefundBackendOrder selectYanchuRefundBackendOrderById(Long id)
    {
        return yanchuRefundBackendOrderMapper.selectYanchuRefundBackendOrderById(id);
    }

    @Override
    public YanchuRefundBackendOrder selectRefundBackendOrderById(Long idDetail){
        YanchuRefundBackendOrder order = yanchuRefundBackendOrderMapper.selectRefundBackendOrderById(idDetail);
        if(null == order){
            return null;
        }
        List<OrderDetailVo> detailVos = yanchuOrderDetailMapper.selectDetailVoListByRefund(order.getId());
        order.setDetailVoList(detailVos);
        return order;
    }

    /**
     * 查询出票退款单列表
     * 
     * @param yanchuRefundBackendOrder 出票退款单
     * @return 出票退款单
     */
    @Override
    public List<YanchuRefundBackendOrder> selectYanchuRefundBackendOrderList(YanchuRefundBackendOrder yanchuRefundBackendOrder)
    {
        return yanchuRefundBackendOrderMapper.selectYanchuRefundBackendOrderList(yanchuRefundBackendOrder);
    }

    /**
     * 新增出票退款单
     * 
     * @param yanchuRefundBackendOrder 出票退款单
     * @return 结果
     */
    @Override
    public int insertYanchuRefundBackendOrder(YanchuRefundBackendOrder yanchuRefundBackendOrder)
    {
        yanchuRefundBackendOrder.setCreateTime(DateUtils.getNowDate());
        return yanchuRefundBackendOrderMapper.insertYanchuRefundBackendOrder(yanchuRefundBackendOrder);
    }

    /**
     * 修改出票退款单
     * 
     * @param yanchuRefundBackendOrder 出票退款单
     * @return 结果
     */
    @Override
    public int updateYanchuRefundBackendOrder(YanchuRefundBackendOrder yanchuRefundBackendOrder)
    {
        return yanchuRefundBackendOrderMapper.updateYanchuRefundBackendOrder(yanchuRefundBackendOrder);
    }

    /**
     * 批量删除出票退款单
     * 
     * @param ids 需要删除的出票退款单主键
     * @return 结果
     */
    @Override
    public int deleteYanchuRefundBackendOrderByIds(Long[] ids)
    {
        return yanchuRefundBackendOrderMapper.deleteYanchuRefundBackendOrderByIds(ids);
    }

    /**
     * 删除出票退款单信息
     * 
     * @param id 出票退款单主键
     * @return 结果
     */
    @Override
    public int deleteYanchuRefundBackendOrderById(Long id)
    {
        return yanchuRefundBackendOrderMapper.deleteYanchuRefundBackendOrderById(id);
    }

    /**
     * 取消已出票订单
     * @param yanchuOrder
     * @param reason
     * @param userId
     * @return
     */
    @Override
    @Async
    public Integer cancelOrderList(YanchuOrder yanchuOrder,String reason,Long userId,YanchuSession session){
        List<OrderVo> list = yanchuOrderMapper.selectPayedOrderVoList(yanchuOrder.getSessionId(),PerformConstants.TICKET_TYPE_BACKEND);
        Integer count = 0;
        if (CollectionUtils.isEmpty(list)) {
            return count;
        }
        YanchuRefundBackendOrder refundOrder = null;
        List<YanchuOrderDetail> details = null;
        for (OrderVo order : list) {
            refundOrder = new YanchuRefundBackendOrder();
            refundOrder.setOrderId(order.getId());
            refundOrder.setRefundType(PerformConstants.REFUND_TYPE);
            refundOrder.setRefundFlag(PerformConstants.REFUND_FLAG_TOTAL);
            refundOrder.setRefundReason(reason);
            refundOrder.setRefundOrderStatus(order.getTicketStatus());
            refundOrder.setCreator(userId);
            if(order.getTotalMoney().compareTo(BigDecimal.ZERO) == 0 || (null!=order.getTicketStatus() && order.getTicketStatus().equals(PerformConstants.TICKET_NOTPAY))){
                refundOrder.setRefundStatus(PerformConstants.REFUND_BACK_REFUND);
            }else{
                refundOrder.setRefundStatus(PerformConstants.REFUND_BACK_TOBEREFUND);//待退款
            }
            details = yanchuOrderDetailMapper.selectPayedOrderDetailList(order.getId());
            List<Long> detailIds = details.stream().map(YanchuOrderDetail::getId).collect(toList());
            String ids = Joiner.on(",").join(detailIds);
            BigDecimal totalRefund = details.stream().map(YanchuOrderDetail::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            refundOrder.setRefundTotalMoney(totalRefund);
            refundOrder.setDetailIds(ids);
            try {
                count += insertYanchuRefundOrder(refundOrder,session);
            }catch (Exception e){
                logger.error("cancelOrderList error",e);
            }
            logger.info("cancelOrderList count:{}",count);
        }
        return count;
    }

    /**
     * 新增退款单
     *
     * @param refundOrder 退款单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertYanchuRefundOrder(YanchuRefundBackendOrder refundOrder, YanchuSession session) {
        logger.info("insertYanchuRefundBackendOrder orderId:{} refundMoney:{} detailIds:{}",refundOrder.getOrderId(),
                refundOrder.getRefundTotalMoney(),refundOrder.getDetailIds());
        YanchuOrder yanchuOrder = yanchuOrderMapper.selectOrderById(refundOrder.getOrderId());
        if(null == yanchuOrder || (!yanchuOrder.getStatus().equals(PerformConstants.ORDER_PAY) &&
                !yanchuOrder.getStatus().equals(PerformConstants.ORDER_CHECKED))){
            throw new ServiceException("订单不存在或状态不正确!");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        refundOrder.setCreateTime(DateUtils.getNowDate());
        refundOrder.setOrderNo(yanchuOrder.getOrderId());
        refundOrder.setCreateTime(new Date());
        refundOrder.setCreator(loginUser.getUser().getUserId());

        if(yanchuOrder.getTotalMoney().compareTo(BigDecimal.ZERO) == 0 ||
                (null != refundOrder.getRefundStatus() && refundOrder.getRefundStatus().equals(PerformConstants.REFUND_BACK_REFUND))){
            refundOrder.setRefundStatus(PerformConstants.REFUND_BACK_REFUND);//已退款
        }else{
            refundOrder.setRefundStatus(PerformConstants.REFUND_BACK_TOBEREFUND);//待退款
        }
        refundOrder.setRefundOrderStatus(yanchuOrder.getTicketStatus());
        String ids = refundOrder.getDetailIds();
        List<Long> idList = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(ids).stream().map(Long::valueOf).collect(toList());

        int count = 0;
        List<YuanchuRefundBackendOrderDetail> details = Lists.newArrayList();
        YuanchuRefundBackendOrderDetail detail = null;
        //1：整单退款；2：部分退款

        refundOrder.setRefundFlag(PerformConstants.REFUND_FLAG_PART);
        List<YanchuOrderDetail> payDetails = yanchuOrderDetailMapper.selectPayedOrderDetailList(yanchuOrder.getId());
        if(CollectionUtils.isNotEmpty(payDetails) && payDetails.size() == idList.size()){
            refundOrder.setRefundFlag(PerformConstants.REFUND_FLAG_TOTAL);
        }
        count = this.insertYanchuRefundBackendOrder(refundOrder);
        for(Long id:idList){
            detail = new YuanchuRefundBackendOrderDetail();
            detail.setRefundOrderId(refundOrder.getId());
            detail.setOrderDetailId(id);
            detail.setOrderId(refundOrder.getOrderId());
            details.add(detail);
        }
        yuanchuRefundBackendOrderDetailMapper.insertBatch(details);
        int countCancel = cancelOrder(yanchuOrder,refundOrder,session,idList);
        logger.info("countCancel:{}",countCancel);
        return count;
    }

    /**
     * 取消出票订单
     *
     * @param yanchuOrder
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cancelOrder(YanchuOrder yanchuOrder,YanchuRefundBackendOrder refundOrder,YanchuSession session,List<Long> idList) {
        int count = 0;
        logger.info("cancelBackendOrder orderNo:{} cardAmt:{} balanceAmt:{} wechatAmt:{}",yanchuOrder.getOrderId(),refundOrder.getRefundTotalMoney());
        LoginUser loginUser = SecurityUtils.getLoginUser();

        //直接更新为已退款
        if(refundOrder.getRefundFlag().equals(PerformConstants.REFUND_FLAG_TOTAL)){//整单退
            //更新订单表
            count = yanchuOrderMapper.updateRefundById(yanchuOrder.getId(), PerformConstants.ORDER_REFUND,
                    null,null,loginUser.getUser().getUserId(),
                    null,null,null);
            if (count == 0) {
                logger.warn("更新支付失败 orderNo:{}", yanchuOrder.getOrderId());
                throw new ServiceException("更新退款状态失败！");
            }
        }

        //更新订单详情表
        count = yanchuOrderDetailMapper.updateOrderDetailById(idList, PerformConstants.ORDER_REFUND,
                null);
        if (count > 0 && (null==session || !session.getStatus().equals(PerformConstants.SESSION_CANCEL))) {
            List<YanchuOrderDetail> details = yanchuOrderDetailMapper.selectOrderDetails(idList);
            List<String> tickets = details.stream().map(YanchuOrderDetail::getTicket).collect(toList());
            //更新座位表
            int seatCount = yanchuSeatMapper.updateBackendSeat(tickets, PerformConstants.TICKET_SEAT_PAY);
            if (seatCount > 0 && (null==session || !session.getStatus().equals(PerformConstants.SESSION_CANCEL))) {
                List<YanchuSeat> seats = yanchuSeatMapper.selectYanchuSeatByTicket(tickets);
                iYanchuSeatService.refreshTicketList(seats,null);
            }
        }
        if(null == session){
            //更新票房、积分
            iYanchuScoreService.reduceNumsMoney(count, refundOrder.getRefundTotalMoney(), yanchuOrder.getSessionId(),
                    yanchuOrder.getUserId(), refundOrder.getRefundTotalMoney().intValue());
        }
        return count;
    }
}
